
#include <stdint.h>
#include <stdlib.h>

#include <Reader/Reader.h>

#include "log2.h"
#include "simple_protocol.h"

#include "config/config3.h"
#include "Reader/reader_samav3.h"

//传输密钥
//50F5B5B24D7070BA8E2F37A7F002D71E
const uint8_t transfer_key[16] = {0x50, 0xF5, 0xB5, 0xB2, 0x4D, 0x70, 0x70, 0xBA, 0x8E, 0x2F, 0x37, 0xA7, 0xF0, 0x02, 0xD7, 0x1E};

/****************************************************************************
M356系列模块 V1.26增加功能：
1、支持高频卡、低频卡寻卡优先选择，默认为高频卡（保持跟v1.25版本相同）
命令格式：
低频卡优先：[FE02][00]\r
高频卡优先：[FE02][01]\r   （默认）

2、支持MF+FeliCa卡同时打开时MF询卡校验，默认为MF卡询卡校验（MF读两次，只有UID一样时才认为有效）（保持跟v1.25版本相同）
命令格式：
关闭MF卡校验：[FE03][00]\r
打开MF卡校验：[FE03][01]\r  （默认）
****************************************************************************/

//防复制配置
static int api_zk_config_hf_first(buffer_t* command, buffer_t* response){
	uint8_t cfg = net_buf_simple_pull_u8(command);
	if(cfg){
		reader.config |= RD_CFG_HFFirst;
	}
	else{
		reader.config &= ~ RD_CFG_HFFirst;
	}
	
	return ERR_NONE;
}



static int api_zk_config_mf_check(buffer_t* command, buffer_t* response){
	uint8_t cfg = net_buf_simple_pull_u8(command);
	if(cfg){
		reader.config |= RD_CFG_MFCheck;
	}
	else{
		reader.config &= ~ RD_CFG_MFCheck;
	}
	return ERR_NONE;
}
/*=====================================================================*/
//设置密钥
int reader_cfg_save_key_to_sam(uint8_t kid, key_t* key);

static int zk_save_key_to_sam(uint8_t kid, key_t* key){
	int ret;
	ret = samav3_activate2();
	if(ret){
		LOG2_ERR("samav3_activate2 fail: %d", ret);
		return ret;
	}
	ret = reader_cfg_save_key_to_sam(kid, key);
	samav3_deactivate();
	if(ret){
		LOG2_ERR("reader_cfg_save_key_to_sam fail: %d", ret);		
	}
	return ret;
}

static int api_zk_set_key(buffer_t* command, buffer_t* response){
	key_t* key = (key_t*)command->data;
	uint8_t kid = key->id;
	kid &= ~ KID_FLASH_MASK;
	//key id 0x30-0xFF有效
	if(kid < 0x30){
		LOG2_ERR("invalid kid %d", kid);
		return -1;
	}
	config3_decrypt(key->data, 16, transfer_key);
	LOG2_DBG("set key id %02X, type %d, ver %d", key->id, key->type, key->ver);
	LOG2_BUF_DBG("key", key->data, 32);
	int ret = 0;

	if(reader_se_support()){
		if(kid & KID_FLASH_MASK){
			ret = config3_set_key(kid, key);
		}

		ret |= zk_save_key_to_sam(kid, key);
	}
	else{
		ret = config3_set_key(kid, key);
	}
		
	API_CHECK(ret);
	config3_update_delay(100);
	return ERR_NONE;
}

#if 0
//获取密钥
static int api_zk_get_key(buffer_t* command, buffer_t* response){
	uint8_t kid = net_buf_simple_pull_u8(command);
	key_t* key = (key_t*)net_buf_simple_tail(response);
	int ret = config3_get_key(kid, key);
	API_CHECK(ret);
	net_buf_simple_add(response, 16 + 3);
	return ERR_NONE;
}
#endif

#pragma pack(push, 1)

typedef struct {
	uint8_t type;
	uint8_t len;
	uint8_t data[0];
}param_tlv_t;

#pragma pack(pop)


//获取参数
static int api_zk_get_param(buffer_t* command, buffer_t* response){
	uint8_t param_id = net_buf_simple_pull_u8(command);
	uint8_t * resp_buf = net_buf_simple_tail(response);
	param_tlv_t* tlv = (param_tlv_t*)resp_buf;

	tlv->type = param_id;
	LOG2_INF("get param id %d", param_id);
	//以TLV格式返回参数
	switch(param_id){
		case 1:
		//苹果钱包参数
			tlv->len = sizeof(param_apple_wallet_t);
			memcpy(tlv->data, &config_param.apple_wallet, tlv->len);
			break;
		case 2:
		//谷歌钱包参数
			tlv->len = sizeof(param_google_wallet_t);
			memcpy(tlv->data, &config_param.google_wallet, tlv->len);
			break;
		case 3:
		//LEAF参数
			tlv->len = sizeof(param_leaf_t);
			memcpy(tlv->data, &config_param.leaf, tlv->len);
			break;
#if 0			
		case 4:{
			//三星pay参数
			tlv->len = sizeof(param_samsung_pay_t);
			memcpy(tlv->data, &config_param.samsung_pay, tlv->len);
		}
		break;
#endif		
		case 4:{
			//Swiftlane参数
			tlv->len = sizeof(param_swiftlane_t);
			memcpy(tlv->data, &config_param.swiftlane, tlv->len);
		}
		break;
		case 5:{
			// AccessGrid参数
			tlv->len = sizeof(param_access_grid_t);
			memcpy(tlv->data, &config_param.access_grid, tlv->len);
		}
		break;		
		default:
			LOG2_ERR("unknown param id %d", param_id);
			return -1;					
	}
	uint8_t rlen = tlv->len+sizeof(param_tlv_t);
	//设置应答数据长度
	net_buf_simple_add(response, rlen);
	//设置Array(Var)长度字段
	net_buf_simple_push_u8(response, rlen);
	return ERR_NONE;
}

//设置参数
static int api_zk_set_param(buffer_t* command, buffer_t* response){
	param_tlv_t* tlv = (param_tlv_t*)(command->data + 1);	//跳过Array(Var)长度字段
	LOG2_INF("set param id %d, len %d", tlv->type, tlv->len);
	uint8_t update = 0;
	
	switch(tlv->type){
	case 1:{
		//苹果钱包参数		
		if(tlv->len < sizeof(param_apple_wallet_t)){
			LOG2_ERR("invalid param 1 length %d, param size is %u", tlv->len, sizeof(param_apple_wallet_t));
			return -1;
		}
		param_apple_wallet_t* param = (param_apple_wallet_t*)tlv->data;
		if(memcmp(&config_param.apple_wallet, param, sizeof(param_apple_wallet_t))){
			memcpy(&config_param.apple_wallet, param, sizeof(param_apple_wallet_t));
			update = 1;
		}
	}
	break;
	case 2:{
		//谷歌钱包参数
		if(tlv->len < sizeof(param_google_wallet_t)){
			LOG2_ERR("invalid param 2 length %d, param size is %u", tlv->len, sizeof(param_google_wallet_t));
			return -1;
		}
		param_google_wallet_t* param = (param_google_wallet_t*)tlv->data;
		if(memcmp(&config_param.google_wallet, param, sizeof(param_google_wallet_t))){
			memcpy(&config_param.google_wallet, param, sizeof(param_google_wallet_t));
			update = 1;
		}
	}
	break;
	case 3:{
		//LEAF参数
		if(tlv->len < sizeof(param_leaf_t)){
			LOG2_ERR("invalid param 3 length %d, param size is %u", tlv->len, sizeof(param_leaf_t));
			return -1;
		}
		param_leaf_t* param = (param_leaf_t*)tlv->data;
		if(memcmp(&config_param.leaf, param, sizeof(param_leaf_t))){
			memcpy(&config_param.leaf, param, sizeof(param_leaf_t));
			update = 1;
		}
	}
	break;
#if 0	
	case 4:{
		//SAMSUNG_PAY参数
		if(tlv->len < sizeof(param_samsung_pay_t)){
			LOG2_ERR("invalid param 4 length %d, param size is %u", tlv->len, sizeof(param_samsung_pay_t));
			return -1;
		}
		param_samsung_pay_t* param = (param_samsung_pay_t*)tlv->data;
		memcpy(&config_param.samsung_pay, param, sizeof(param_samsung_pay_t));
	}
	break;
#endif	
	case 4: {
		if(tlv->len < sizeof(param_swiftlane_t)){
			LOG2_ERR("invalid param 5 length %d, param size is %u", tlv->len, sizeof(param_swiftlane_t));
			return -1;
		}
		param_swiftlane_t* param = (param_swiftlane_t*)tlv->data;
		if(memcmp(&config_param.swiftlane, param, sizeof(param_swiftlane_t))){
			memcpy(&config_param.swiftlane, param, sizeof(param_swiftlane_t));
			update = 1;
		}
	}
	break;
	case 5:{
		// AccessGrid参数
		if(tlv->len < sizeof(param_access_grid_t)){
			LOG2_ERR("invalid param 6 length %d, param size is %u", tlv->len, sizeof(param_access_grid_t));
			return -1;
		}
		param_access_grid_t* param = (param_access_grid_t*)tlv->data;
		if(memcmp(&config_param.access_grid, param, sizeof(param_access_grid_t))){
			memcpy(&config_param.access_grid, param, sizeof(param_access_grid_t));
			update = 1;
		}
		
	}
	break;
	default:{
		LOG2_ERR("invalid param type %d", tlv->type);
		return -1;
	}
	}
	
	if(!update){
		LOG2_INF("param not change");
		return ERR_NONE;
	}
	config3_update(CFG_FLAG_UPDATE_PARAM);
	config3_update_delay(100);	
	
	return ERR_NONE;
}

/*=====================================================================*/

static const api_entry_t api_zk_list[] = {
	[0] = NULL,
	[1] = NULL,
	[2] = api_zk_config_hf_first,
	[3] = api_zk_config_mf_check,
	[4] = api_zk_set_param,
	[5] = api_zk_get_param,
	[6] = api_zk_set_key,
};
	
static int zk_api(buffer_t* command, buffer_t* response){
	const uint8_t num = sizeof(api_zk_list)/sizeof(api_zk_list[0]);
	int ret = protocol_call_api(api_zk_list, num, command, response);
	if(ret > 0){
		return ret;
	}
	protocol_response_result(response, ret);
	return ERR_NONE;
}

SIMPLE_API_DEFINE(API_CLASS_ZK, zk_api);


